﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SolarWinds.Shapes;

namespace SolarWinds.Renderers
{
    class BoundingBoxRenderer : DrawableGameComponent
    {
        private VertexBuffer mVertexBuffer;
        private VertexDeclaration mVertexDeclaration;
        private IndexBuffer mIndexBuffer;
        private BasicEffect mBasicEffect;

        public Color LineColor = Color.Yellow;

        public GameComponentCollection Components;

        public BoundingBoxRenderer(Game game) : base(game)
        {
        }

        public override void  Draw(GameTime gameTime)
        {
 	        base.Draw(gameTime);
 
            GraphicsDevice device = Game.GraphicsDevice;

            device.Vertices[0].SetSource(mVertexBuffer, 0, VertexPositionColor.SizeInBytes);
            device.VertexDeclaration = mVertexDeclaration;
            device.Indices = mIndexBuffer;

            foreach (IGameComponent component in Components)
            {
                var shape = component as Shape;
                if (shape != null &&
                    shape.BoundingBoxVisible)
                {
                    Matrix bbWorld = Matrix.CreateScale((shape.BoundingBox.Max - shape.BoundingBox.Min) * 0.5f) * shape.World;

                    // set effect parameters
                    mBasicEffect.World = bbWorld;
                    mBasicEffect.View = SolarWindsGame.Camera.View;
                    mBasicEffect.Projection = SolarWindsGame.Camera.Projection;
                    mBasicEffect.DiffuseColor = LineColor.ToVector3();
                    mBasicEffect.CommitChanges();

                    mBasicEffect.Begin();
                    foreach (EffectPass pass in mBasicEffect.CurrentTechnique.Passes)
                    {
                        pass.Begin();

                        device.RenderState.PointSize = 5;
                        device.DrawPrimitives(PrimitiveType.PointList, 0, 8);
                        device.DrawIndexedPrimitives(PrimitiveType.LineList, 0, 0, 8, 0, 12);

                        pass.End();
                    }
                    mBasicEffect.End();
                }
            }
        }

        protected override void LoadContent()
        {
            GraphicsDevice device = Game.GraphicsDevice;

            // vertex buffer
            mVertexBuffer = new VertexBuffer(device, typeof(VertexPositionColor),
                                             8, BufferUsage.WriteOnly);

            var data = new VertexPositionColor[8];

            int vi = 0;
            data[vi].Position = new Vector3(-1.0f, -1.0f, -1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(1.0f, -1.0f, -1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(1.0f, 1.0f, -1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(-1.0f, 1.0f, -1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(-1.0f, -1.0f, 1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(1.0f, -1.0f, 1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(1.0f, 1.0f, 1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            data[vi].Position = new Vector3(-1.0f, 1.0f, 1.0f);
            data[vi].Color = Color.Yellow;
            ++vi;

            mVertexBuffer.SetData(data);

            // vertex declaration
            mVertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);

            // index buffer
            mIndexBuffer = new IndexBuffer(device,
                                           typeof(short), 24, BufferUsage.WriteOnly);

            short[] indexData = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 };
            mIndexBuffer.SetData(indexData);

            // effect
            mBasicEffect = new BasicEffect(device, null);
            //mBasicEffect.EnableDefaultLighting();

            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();

            if (mVertexBuffer != null)
            {
                mVertexBuffer.Dispose();
                mVertexBuffer = null;
            }

            if (mVertexDeclaration != null)
            {
                mVertexDeclaration.Dispose();
                mVertexDeclaration = null;
            }

            if (mIndexBuffer != null)
            {
                mIndexBuffer.Dispose();
                mIndexBuffer = null;
            }

            if (mBasicEffect != null)
            {
                mBasicEffect.Dispose();
                mBasicEffect = null;
            }
        }
    }
}
